{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Appendix 10.1: Chaining Prompts\n",
    "\n",
    "- [Lesson](#lesson)\n",
    "- [Example Playground](#example-playground)\n",
    "\n",
    "## Setup\n",
    "\n",
    "Run the following setup cell to load your API key and establish the `get_completion` helper function."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Import python's built-in regular expression library\n",
    "import re\n",
    "import boto3\n",
    "from botocore.exceptions import ClientError\n",
    "import json\n",
    "\n",
    "# Import the hints module from the utils package\n",
    "from utils import hints\n",
    "\n",
    "# Retrieve the MODEL_NAME variable from the IPython store\n",
    "%store -r modelId\n",
    "%store -r region\n",
    "\n",
    "bedrock_client = boto3.client(service_name='bedrock-runtime', region_name=region)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "def get_completion(messages, system_prompt=None):\n",
    "    inference_config = {\n",
    "        \"temperature\": 0.5,\n",
    "        \"maxTokens\": 200\n",
    "    }\n",
    "    converse_api_params = {\n",
    "        \"modelId\": modelId,\n",
    "        \"messages\": messages,\n",
    "        \"inferenceConfig\": inference_config\n",
    "    }\n",
    "    if system_prompt:\n",
    "        converse_api_params[\"system\"] = [{\"text\": system_prompt}]\n",
    "    try:\n",
    "        response = bedrock_client.converse(**converse_api_params)\n",
    "        text_content = response['output']['message']['content'][0]['text']\n",
    "        return text_content\n",
    "\n",
    "    except ClientError as err:\n",
    "        message = err.response['Error']['Message']\n",
    "        print(f\"A client error occured: {message}\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Lesson\n",
    "\n",
    "The saying goes, \"Writing is rewriting.\" It turns out, **Claude can often improve the accuracy of its response when asked to do so**!\n",
    "\n",
    "There are many ways to prompt Claude to \"think again\". The ways that feel natural to ask a human to double check their work will also generally work for Claude. (Check out our [prompt chaining documentation](https://docs.anthropic.com/claude/docs/chain-prompts) for further examples of when and how to use prompt chaining.)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Examples\n",
    "\n",
    "In this example, we ask Claude to come up with ten words... but one or more of them isn't a real word."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initial prompt\n",
    "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\"role\": \"user\",\n",
    "     \"content\": [{\"text\": first_user}]}\n",
    "]\n",
    "\n",
    "# Store and print Claude's response\n",
    "first_response = get_completion(messages)\n",
    "print(first_response)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Asking Claude to make its answer more accurate** fixes the error! \n",
    "\n",
    "Below, we've pulled down Claude's incorrect response from above and added another turn to the conversation asking Claude to fix its previous answer."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "second_user = \"Please find replacements for all 'words' that are not real words.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "But is Claude revising its answer just because we told it to? What if we start off with a correct answer already? Will Claude lose its confidence? Here, we've placed a correct response in the place of `first_response` and asked it to double check again."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
    "\n",
    "first_response = \"\"\"Here are 10 words that end with the letters 'ab':\n",
    "\n",
    "1. Cab\n",
    "2. Dab\n",
    "3. Grab\n",
    "4. Gab\n",
    "5. Jab\n",
    "6. Lab\n",
    "7. Nab\n",
    "8. Slab\n",
    "9. Tab\n",
    "10. Blab\"\"\"\n",
    "\n",
    "second_user = \"Please find replacements for all 'words' that are not real words.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "You may notice that if you generate a respnse from the above block a few times, Claude leaves the words as is most of the time, but still occasionally changes the words even though they're all already correct. What can we do to mitigate this? Per Chapter 8, we can give Claude an out! Let's try this one more time."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
    "\n",
    "first_response = \"\"\"Here are 10 words that end with the letters 'ab':\n",
    "\n",
    "1. Cab\n",
    "2. Dab\n",
    "3. Grab\n",
    "4. Gab\n",
    "5. Jab\n",
    "6. Lab\n",
    "7. Nab\n",
    "8. Slab\n",
    "9. Tab\n",
    "10. Blab\"\"\"\n",
    "\n",
    "second_user = \"Please find replacements for all 'words' that are not real words. If all the words are real words, return the original list.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Try generating responses from the above code a few times to see that Claude is much better at sticking to its guns now.\n",
    "\n",
    "You can also use prompt chaining to **ask Claude to make its responses better**. Below, we asked Claude to first write a story, and then improve the story it wrote. Your personal tastes may vary, but many might agree that Claude's second version is better.\n",
    "\n",
    "First, let's generate Claude's first version of the story."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initial prompt\n",
    "first_user = \"Write a three-sentence short story about a girl who likes to run.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": first_user}]\n",
    "    }\n",
    "]\n",
    "\n",
    "# Store and print Claude's response\n",
    "first_response = get_completion(messages)\n",
    "print(first_response)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now let's have Claude improve on its first draft."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "second_user = \"Make the story better.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This form of substitution is very powerful. We've been using substitution placeholders to pass in lists, words, Claude's former responses, and so on. You can also **use substitution to do what we call \"function calling,\" which is asking Claude to perform some function, and then taking the results of that function and asking Claude to do even more afterward with the results**. It works like any other substitution. More on this in the next appendix.\n",
    "\n",
    "Below is one more example of taking the results of one call to Claude and plugging it into another, longer call. Let's start with the first prompt (which includes prefilling Claude's response this time)."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_user = \"\"\"Find all names from the below text:\n",
    "\n",
    "\"Hey, Jesse. It's me, Erin. I'm calling about the party that Joey is throwing tomorrow. Keisha said she would come and I think Mel will be there too.\"\"\"\n",
    "\n",
    "prefill = \"<names>\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": prefill}]\n",
    "    }\n",
    "]\n",
    "\n",
    "# Store and print Claude's response\n",
    "first_response = get_completion(messages)\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(first_response)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Let's pass this list of names into another prompt."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "second_user = \"Alphabetize the list.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": prefill + \"\\n\" + first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Now that you've learned about prompt chaining, head over to Appendix 10.2 to learn how to implement function calling using prompt chaining."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "\n",
    "## Example Playground\n",
    "\n",
    "This is an area for you to experiment freely with the prompt examples shown in this lesson and tweak prompts to see how it may affect Claude's responses."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initial prompt\n",
    "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\"role\": \"user\",\n",
    "     \"content\": [{\"text\": first_user}]}\n",
    "]\n",
    "\n",
    "# Store and print Claude's response\n",
    "first_response = get_completion(messages)\n",
    "print(first_response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "second_user = \"Please find replacements for all 'words' that are not real words.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
    "\n",
    "first_response = \"\"\"Here are 10 words that end with the letters 'ab':\n",
    "\n",
    "1. Cab\n",
    "2. Dab\n",
    "3. Grab\n",
    "4. Gab\n",
    "5. Jab\n",
    "6. Lab\n",
    "7. Nab\n",
    "8. Slab\n",
    "9. Tab\n",
    "10. Blab\"\"\"\n",
    "\n",
    "second_user = \"Please find replacements for all 'words' that are not real words.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_user = \"Name ten words that all end with the exact letters 'ab'.\"\n",
    "\n",
    "first_response = \"\"\"Here are 10 words that end with the letters 'ab':\n",
    "\n",
    "1. Cab\n",
    "2. Dab\n",
    "3. Grab\n",
    "4. Gab\n",
    "5. Jab\n",
    "6. Lab\n",
    "7. Nab\n",
    "8. Slab\n",
    "9. Tab\n",
    "10. Blab\"\"\"\n",
    "\n",
    "second_user = \"Please find replacements for all 'words' that are not real words. If all the words are real words, return the original list.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "# Initial prompt\n",
    "first_user = \"Write a three-sentence short story about a girl who likes to run.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": first_user}]\n",
    "    }\n",
    "]\n",
    "\n",
    "# Store and print Claude's response\n",
    "first_response = get_completion(messages)\n",
    "print(first_response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "second_user = \"Make the story better.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "first_user = \"\"\"Find all names from the below text:\n",
    "\n",
    "\"Hey, Jesse. It's me, Erin. I'm calling about the party that Joey is throwing tomorrow. Keisha said she would come and I think Mel will be there too.\"\"\"\n",
    "\n",
    "prefill = \"<names>\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": prefill}]\n",
    "    }\n",
    "]\n",
    "\n",
    "# Store and print Claude's response\n",
    "first_response = get_completion(messages)\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(first_response)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "tags": []
   },
   "outputs": [],
   "source": [
    "second_user = \"Alphabetize the list.\"\n",
    "\n",
    "# API messages array\n",
    "messages = [\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "        \"content\": [{\"text\": first_user}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"assistant\",\n",
    "         \"content\": [{\"text\": prefill + \"\\n\" + first_response}]\n",
    "    },\n",
    "    {\n",
    "        \"role\": \"user\",\n",
    "         \"content\": [{\"text\": second_user}]\n",
    "    },\n",
    "\n",
    "]\n",
    "\n",
    "# Print Claude's response\n",
    "print(\"------------------------ Full messsages array with variable substutions ------------------------\")\n",
    "print(messages)\n",
    "print(\"\\n------------------------------------- Claude's response -------------------------------------\")\n",
    "print(get_completion(messages))"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "conda_tensorflow2_p310",
   "language": "python",
   "name": "conda_tensorflow2_p310"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.14"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
